bitkeeper revision 1.102.1.1 (3e63780anLue1rOR9-4fOlXH3ejAhA)
authorkaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk>
Mon, 3 Mar 2003 15:43:06 +0000 (15:43 +0000)
committerkaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk>
Mon, 3 Mar 2003 15:43:06 +0000 (15:43 +0000)
dom_mem_ops.h, balloon.c, Makefile, dom_mem_ops.c, README:
  new file
Many files:
  Boris's balloon driver.

18 files changed:
.rootkeys
tools/balloon/Makefile [new file with mode: 0644]
tools/balloon/README [new file with mode: 0644]
tools/balloon/balloon.c [new file with mode: 0644]
xen/arch/i386/entry.S
xen/common/dom_mem_ops.c [new file with mode: 0644]
xen/common/domain.c
xen/common/memory.c
xen/include/hypervisor-ifs/hypervisor-if.h
xen/include/xeno/dom_mem_ops.h [new file with mode: 0644]
xen/include/xeno/sched.h
xenolinux-2.4.21-pre4-sparse/arch/xeno/Makefile
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/Makefile [new file with mode: 0644]
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/balloon.c [new file with mode: 0644]
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/dom_mem_ops.h [new file with mode: 0644]
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/dom0/dom0_core.c
xenolinux-2.4.21-pre4-sparse/include/asm-xeno/hypervisor.h
xenolinux-2.4.21-pre4-sparse/include/asm-xeno/page.h

index 79b0d1d19730ec6989c066c057044e5cb3eb00b6..b72dac2fc58576175fc15476beb72414c9917ab3 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3e15d52e0_j129JPvo7xfYGndVFpwQ old/xenolinux-2.4.16-sparse/mm/memory.c
 3e15d535DLvpzTrLRUIerB69LpJD1g old/xenolinux-2.4.16-sparse/mm/mremap.c
 3e15d531m1Y1_W8ki64AFOU_ua4C4w old/xenolinux-2.4.16-sparse/mm/swapfile.c
+3e6377b24eQqYMsDi9XrFkIgTzZ47A tools/balloon/Makefile
+3e6377d6eiFjF1hHIS6JEIOFk62xSA tools/balloon/README
+3e6377dbGcgnisKw16DPCaND7oGO3Q tools/balloon/balloon.c
 3e4d00468-FN2VDeEHo96zxrMHK_mA tools/domain_builder/Makefile
 3e4d0046SPau_y0sw2WLJz8QkqNoRA tools/domain_builder/README
 3e4d0046bbdH0GsI9J_1Eb4ZQHfIiQ tools/domain_builder/dom0_defs.h
 3ddb79bddEYJbcURvqqcx99Yl2iAhQ xen/common/block.c
 3ddb79bdrqnW93GR9gZk1OJe1qK-iQ xen/common/brlock.c
 3ddb79bdLX_P6iB7ILiblRLWvebapg xen/common/dom0_ops.c
+3e6377e4i0c9GtKN65e99OtRbw3AZw xen/common/dom_mem_ops.c
 3ddb79bdYO5D8Av12NHqPeSviav7cg xen/common/domain.c
 3e32af9aRnYGl4GMOaDKp7JdfhOGhg xen/common/domain_page.c
 3ddb79bdeyutmaXEfpQvvxj7eQ0fCw xen/common/event.c
 3ddb79c1V44RD26YqCUm-kqIupM37A xen/include/xeno/ctype.h
 3ddb79c05DdHQ0UxX_jKsXdR4QlMCA xen/include/xeno/delay.h
 3ddb79c2PMeWTK86y4C3F4MzHw4A1g xen/include/xeno/dom0_ops.h
+3e6377eaioRoNm0m_HSDEAd4Vqrq_w xen/include/xeno/dom_mem_ops.h
 3ddb79c1uaWQZj551j1O0B5z8AnHOg xen/include/xeno/elevator.h
 3ddb79c0HIghfBF8zFUdmXhOU8i6hA xen/include/xeno/errno.h
 3ddb79c0rMjudDKkJku_mkm0J-BZgw xen/include/xeno/etherdevice.h
 3e5a4e65n-KhsEAs-A4ULiStBp-r6w xenolinux-2.4.21-pre4-sparse/arch/xeno/boot/Makefile
 3e5a4e65OV_j_DBtjzt5vej771AJsA xenolinux-2.4.21-pre4-sparse/arch/xeno/config.in
 3e5a4e65TNEycLeXqPSXQJQm_xGecA xenolinux-2.4.21-pre4-sparse/arch/xeno/defconfig
+3e6377f5xwPfYZkPHPrDbEq1PRN7uQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/Makefile
+3e6377f8Me8IqtvEhb70XFgOvqQH7A xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/balloon.c
+3e6377fbMjXWAQd0XN0FWv4fDEo6fg xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/dom_mem_ops.h
 3e5a4e65iHEuC5sjFhj42XALYbLVRw xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile
 3e5a4e65pP5spJErBW69pJxSSdK9RA xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c
 3e5a4e65GtI9JZRAjuRdXaxt_4ohyQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c
diff --git a/tools/balloon/Makefile b/tools/balloon/Makefile
new file mode 100644 (file)
index 0000000..49bab90
--- /dev/null
@@ -0,0 +1,9 @@
+CC = gcc
+TARGET=balloon
+
+TARGET: balloon.c
+       $(CC) -O2 -Wall -o $(TARGET) balloon.c
+
+clean:
+       $(RM) *.o $(TARGET) *~
+
diff --git a/tools/balloon/README b/tools/balloon/README
new file mode 100644 (file)
index 0000000..430e8f4
--- /dev/null
@@ -0,0 +1,17 @@
+Xeno Balloon driver supports two operations:
+
+1. Inflating - which means domain giving up pages of mem to xen.
+2. Deflating - which means reclaiming memory pages from xen.
+
+Currently, domain can only claim pages from xen up to the number of 
+previously released ones. This is to change. 
+
+Example:
+
+# balloon inflate 1000
+
+Give up 1000 pages to xen.
+
+# balloon deflate 1000
+
+Claim 1000 pages from xen.
diff --git a/tools/balloon/balloon.c b/tools/balloon/balloon.c
new file mode 100644 (file)
index 0000000..9c90a7a
--- /dev/null
@@ -0,0 +1,114 @@
+/******************************************************************************
+ * balloon.c
+ *
+ * Xeno balloon driver userspace control tool. Used to shrink/grow domain's 
+ * memory.
+ *
+ * Copyright (c) 2003, B Dragovic
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define INFLATE_BALLOON      "inflate"   /* return mem to hypervisor */
+#define DEFLATE_BALLOON      "deflate"   /* claim mem from hypervisor */
+
+/* THIS IS TAKEN FROM XENOLINUX BALLOON DRIVER */
+#define USER_INFLATE_BALLOON  1   /* return mem to hypervisor */
+#define USER_DEFLATE_BALLOON  2   /* claim mem from hypervisor */
+typedef struct user_balloon_op {
+    unsigned int    op;
+    unsigned long   size;
+} user_balloon_op_t;
+/* END OF CODE TAKEN FROM XENOLINUX BALLOON DRIVER */
+
+
+static int open_balloon_proc()
+{
+    return open("/proc/xeno/balloon", O_RDWR);
+}
+
+/* inflate balloon function signals to kernel it should relinquish memory */
+static int inflate_balloon(unsigned long num_pages)
+{
+    user_balloon_op_t bop;
+    int proc_fd;
+
+    if((proc_fd = open_balloon_proc()) <= 0){
+        printf("Error opening balloon proc file.\n");
+        return 0;
+    }
+
+    bop.op   = USER_INFLATE_BALLOON;
+    bop.size = num_pages;
+    if ( write(proc_fd, &bop, sizeof(bop)) <= 0 )
+    {
+        printf("Error writing to balloon proc file.\n");
+        return 0;
+    }
+
+    close(proc_fd);
+    return 1;
+}
+
+/* deflate balloon function signals to kernel it should claim memory */
+static int deflate_balloon(unsigned long num_pages)
+{
+    user_balloon_op_t bop;
+    int proc_fd;
+
+    if((proc_fd = open_balloon_proc()) <= 0){
+        printf("Error opening balloon proc file.\n");
+        return 0;
+    }
+
+    bop.op   = USER_DEFLATE_BALLOON;
+    bop.size = num_pages;
+    if(write(proc_fd, &bop, sizeof(bop)) <= 0){
+        printf("Error writing to balloon proc file.\n");
+        return 0;
+    }
+
+    close(proc_fd);
+    return 1;
+}
+
+int main(int argc, char *argv[])
+{
+    unsigned long num_pages;
+
+    if(argc < 2){
+        printf("Usage: balloon <inflate|deflate> <num_pages>\n");
+        return -1;
+    }
+
+    num_pages = atol(argv[2]);
+
+    if(!strcmp(argv[1], INFLATE_BALLOON)){
+        if(!inflate_balloon(num_pages)){
+            perror("Inflating balloon failed");
+            return -1;
+        }
+
+    } else if (!strcmp(argv[1], DEFLATE_BALLOON)){
+        if(!deflate_balloon(num_pages)){
+            perror("Deflating balloon failed");
+            return -1;
+        }
+
+    } else {
+        printf("Unrecognized command line argument.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+    
+
index 928a96ed4ec499cc2ea82733f690665205f48e62..cd4957816884092e6d0d84983db4e72cf24b2279 100644 (file)
@@ -529,6 +529,7 @@ ENTRY(hypervisor_call_table)
         .long SYMBOL_NAME(do_get_debugreg)
         .long SYMBOL_NAME(do_update_descriptor)
         .long SYMBOL_NAME(do_set_fast_trap)
+        .long SYMBOL_NAME(do_dom_mem_op)
         .rept NR_syscalls-(.-hypervisor_call_table)/4
         .long SYMBOL_NAME(sys_ni_syscall)
        .endr
diff --git a/xen/common/dom_mem_ops.c b/xen/common/dom_mem_ops.c
new file mode 100644 (file)
index 0000000..08a4765
--- /dev/null
@@ -0,0 +1,144 @@
+/******************************************************************************
+ * dom_mem_ops.c
+ *
+ * Code to handle memory related requests from domains eg. balloon driver.
+ *
+ * Copyright (c) 2003, B Dragovic
+ */
+
+#include <xeno/config.h>
+#include <xeno/types.h>
+#include <xeno/lib.h>
+#include <xeno/dom_mem_ops.h>
+#include <xeno/sched.h>
+#include <xeno/event.h>
+#include <asm/domain_page.h>
+
+#if 1
+#define DPRINTK(_f, _a...) printk( _f , ## _a )
+#else
+#define DPRINTK(_f, _a...) ((void)0)
+#endif
+
+static long alloc_dom_mem(struct task_struct *p, balloon_def_op_t bop)
+{
+    struct list_head *temp;
+    struct pfn_info  *pf;     /* pfn_info of current page */
+    unsigned long     mpfn;   /* machine frame number of current page */
+    void             *va;     /* Xen-usable mapping of current page */
+    unsigned long     i;
+    unsigned long     flags;
+
+    /* POLICY DECISION: Each domain has a page limit. */
+    if( (p->tot_pages + bop.size) > p->max_pages )
+        return -ENOMEM;
+
+    if ( free_pfns < bop.size ) 
+        return -ENOMEM;
+    
+    spin_lock_irqsave(&free_list_lock, flags);
+    
+    temp = free_list.next;
+    for ( i = 0; i < bop.size; i++ )
+    {
+        /* Get a free page and add it to the domain's page list. */
+        pf = list_entry(temp, struct pfn_info, list);
+        pf->flags |= p->domain;
+        pf->type_count = pf->tot_count = 0;
+        temp = temp->next;
+        list_del(&pf->list);
+        list_add_tail(&pf->list, &p->pg_head);
+        free_pfns--;
+
+        p->tot_pages++;
+
+        /* Inform the domain of the new page's machine address. */ 
+        mpfn = (unsigned long)(pf - frame_table);
+        copy_to_user(bop.pages, &mpfn, sizeof(mpfn));
+        bop.pages++; 
+
+        /* Zero out the page to prevent information leakage. */
+        va = map_domain_mem(mpfn << PAGE_SHIFT);
+        memset(va, 0, PAGE_SIZE);
+        unmap_domain_mem(va);
+    }
+
+    spin_unlock_irqrestore(&free_list_lock, flags);
+    
+    return bop.size;
+}
+    
+static long free_dom_mem(struct task_struct *p, balloon_inf_op_t bop)
+{
+    struct list_head *temp;
+    struct pfn_info  *pf;     /* pfn_info of current page */
+    unsigned long     mpfn;   /* machine frame number of current page */
+    unsigned long     i;
+    unsigned long     flags;
+    long              rc = 0;
+
+    spin_lock_irqsave(&free_list_lock, flags);
+    
+    temp = free_list.next;
+    for ( i = 0; i < bop.size; i++ )
+    {
+        copy_from_user(&mpfn, bop.pages, sizeof(mpfn));
+        bop.pages++;
+        if ( mpfn >= max_page )
+        {
+            DPRINTK("Domain %d page number out of range (%08lx>=%08lx)\n", 
+                    p->domain, mpfn, max_page);
+            rc = -EINVAL;
+            goto out;
+        }
+
+        pf = &frame_table[mpfn];
+        if ( (pf->type_count != 0) || 
+             (pf->type_count != 0) ||
+             (pf->flags != p->domain) )
+        {
+            DPRINTK("Bad page free for domain %d (%ld, %ld, %08lx)\n",
+                    p->domain, pf->type_count, pf->tot_count, pf->flags);
+            rc = -EINVAL;
+            goto out;
+        }
+
+        pf->flags = 0;
+
+        list_del(&pf->list);
+        list_add(&pf->list, &free_list);
+        free_pfns++;
+
+        p->tot_pages--;
+    }
+
+ out:
+    spin_unlock_irqrestore(&free_list_lock, flags);
+    
+    return rc ? rc : bop.size;
+}
+    
+long do_dom_mem_op(dom_mem_op_t *mem_op)
+{
+    dom_mem_op_t dmop;
+    unsigned long ret = 0;
+
+    if ( copy_from_user(&dmop, mem_op, sizeof(dom_mem_op_t)) )
+        return -EFAULT;
+
+    switch ( dmop.op )
+    {
+    case BALLOON_DEFLATE_OP:
+        ret = alloc_dom_mem(current, dmop.u.balloon_deflate); 
+        break;
+
+    case BALLOON_INFLATE_OP:
+        ret = free_dom_mem(current, dmop.u.balloon_inflate); 
+        break;
+
+    default:
+        printk("Bad memory operation request %08x.\n", dmop.op);
+    }
+
+    return ret;    
+}
index 89efe59f648e81d72377acda5f649e4ffacdfde2..0654cecdfc0811ae2d4897676e4c70e3e85e278a 100644 (file)
@@ -63,7 +63,7 @@ struct task_struct *do_newdomain(unsigned int dom_id, unsigned int cpu)
 
     p->net_ring_base = (net_ring_t *)(p->shared_info + 1);
     INIT_LIST_HEAD(&p->pg_head);
-    p->tot_pages = 0;
+    p->max_pages = p->tot_pages = 0;
     write_lock_irqsave(&tasklist_lock, flags);
     SET_LINKS(p);
     write_unlock_irqrestore(&tasklist_lock, flags);
@@ -177,6 +177,9 @@ unsigned int alloc_new_dom_mem(struct task_struct *p, unsigned int kbytes)
     
     p->tot_pages = req_pages;
 
+    // temporary, max_pages should be explicitly specified
+    p->max_pages = p->tot_pages;
+
     return 0;
 }
  
index 0c534ad3d11c32e345f4fc95ec1ca426ff13b6b6..4a0304aaf84a831c3b84b97d1e6332e81c32358f 100644 (file)
@@ -768,7 +768,7 @@ int do_process_page_updates(page_update_request_t *ureqs, int count)
             {
                 MEM_LOG("Bad domain MPT update (dom %d, pfn %ld)",
                         current->domain, pfn);
-            }
+            }            
             break;
 
             /*
index 6ecac5848edc7fa203743d37e894d63d6ae39768..31cc8b18d8a697cad47a70adb9bc132752ccb393 100644 (file)
@@ -38,13 +38,13 @@ typedef struct
  * Extended requests specify command in least 8 bits of 'value'.
  */
 /* A normal page-table update request. */
-#define PGREQ_NORMAL           0
+#define PGREQ_NORMAL            0
 /* Update an entry in the machine->physical mapping table. */
-#define PGREQ_MPT_UPDATE       1
+#define PGREQ_MPT_UPDATE        1
 /* An extended command. */
-#define PGREQ_EXTENDED_COMMAND 2
+#define PGREQ_EXTENDED_COMMAND  2
 /* DOM0 can make entirely unchecked updates which do not affect refcnts. */
-#define PGREQ_UNCHECKED_UPDATE 3
+#define PGREQ_UNCHECKED_UPDATE  3
     unsigned long ptr, val; /* *ptr = val */
 /* Announce a new top-level page table. */
 #define PGEXT_PIN_L1_TABLE      0
@@ -90,6 +90,7 @@ typedef struct
 #define __HYPERVISOR_get_debugreg         13
 #define __HYPERVISOR_update_descriptor    14
 #define __HYPERVISOR_set_fast_trap        15
+#define __HYPERVISOR_dom_mem_op           16
 
 #define TRAP_INSTR "int $0x82"
 
diff --git a/xen/include/xeno/dom_mem_ops.h b/xen/include/xeno/dom_mem_ops.h
new file mode 100644 (file)
index 0000000..0aaddf2
--- /dev/null
@@ -0,0 +1,31 @@
+/******************************************************************************
+ * dom_mem_ops.h
+ *
+ * Header file supporting domain related memory operations. N.B. keep in sync
+ * with xen version. 
+ *
+ * Copyright (c) 2003, B Dragovic
+ */
+
+#define BALLOON_DEFLATE_OP   0
+#define BALLOON_INFLATE_OP   1
+
+typedef struct balloon_deflate_op {
+    unsigned long   size;
+    unsigned long   * pages;
+} balloon_def_op_t;
+
+typedef struct balloon_inflate_op {
+    unsigned long   size;
+    unsigned long   * pages;
+} balloon_inf_op_t;
+
+typedef struct dom_mem_ops
+{
+    unsigned int op;
+    union
+    {
+        balloon_def_op_t balloon_deflate;
+        balloon_inf_op_t balloon_inflate;
+    } u;
+} dom_mem_op_t;
index b0855f7b0ac828837343481851104aa826f02e42..d89b9f47f14ecd71919d0a3a3fe1c11854524234 100644 (file)
@@ -67,7 +67,8 @@ struct task_struct {
     shared_info_t *shared_info;
     
     struct list_head pg_head;
-    unsigned int tot_pages;
+    unsigned int tot_pages;     /* number of pages currently possesed */
+    unsigned int max_pages;     /* max number of pages that can be possesed */
 
     /* Network I/O */
     net_ring_t *net_ring_base;
index 544af8460584a8c45238a7b333f638fb377677dc..557fe98217a9426bdaba4fa44bc34c76b22a9ed3 100644 (file)
@@ -47,12 +47,14 @@ HEAD := arch/xeno/kernel/head.o arch/xeno/kernel/init_task.o
 SUBDIRS += arch/xeno/kernel arch/xeno/mm arch/xeno/lib
 SUBDIRS += arch/xeno/drivers/console arch/xeno/drivers/network
 SUBDIRS += arch/xeno/drivers/dom0 arch/xeno/drivers/block
+SUBDIRS += arch/xeno/drivers/balloon
 
 CORE_FILES += arch/xeno/kernel/kernel.o arch/xeno/mm/mm.o
 CORE_FILES += arch/xeno/drivers/console/con.o
 CORE_FILES += arch/xeno/drivers/block/blk.o
 CORE_FILES += arch/xeno/drivers/network/net.o
 CORE_FILES += arch/xeno/drivers/dom0/dom0.o
+CORE_FILES += arch/xeno/drivers/balloon/balloon_driver.o
 LIBS := $(TOPDIR)/arch/xeno/lib/lib.a $(LIBS) $(TOPDIR)/arch/xeno/lib/lib.a
 
 arch/xeno/kernel: dummy
@@ -73,6 +75,9 @@ arch/xeno/drivers/block: dummy
 arch/xeno/drivers/dom0: dummy
        $(MAKE) linuxsubdirs SUBDIRS=arch/xeno/drivers/dom0
 
+arch/xeno/drivers/balloon: dummy
+       $(MAKE) linuxsubdirs SUBDIRS=arch/xeno/drivers/balloon
+
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
 vmlinux: arch/xeno/vmlinux.lds
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/Makefile b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/Makefile
new file mode 100644 (file)
index 0000000..f780a51
--- /dev/null
@@ -0,0 +1,3 @@
+O_TARGET := balloon_driver.o
+obj-y := balloon.o
+include $(TOPDIR)/Rules.make
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/balloon.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/balloon.c
new file mode 100644 (file)
index 0000000..abe5884
--- /dev/null
@@ -0,0 +1,275 @@
+/******************************************************************************
+ * balloon.c
+ *
+ * Xeno balloon driver - enables returning/claiming memory to/from xen
+ *
+ * Copyright (c) 2003, B Dragovic
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/smp_lock.h>
+#include <linux/pagemap.h>
+
+#include <asm/hypervisor.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/tlb.h>
+
+#include "dom_mem_ops.h"
+
+/* USER DEFINES -- THESE SHOULD BE COPIED TO USER-SPACE TOOLS */
+#define USER_INFLATE_BALLOON  1   /* return mem to hypervisor */
+#define USER_DEFLATE_BALLOON  2   /* claim mem from hypervisor */
+typedef struct user_balloon_op {
+    unsigned int  op;
+    unsigned long size;
+} user_balloon_op_t;
+/* END OF USER DEFINE */
+
+/* Dead entry written into ballon-owned entries in the PMT. */
+#define DEAD 0xdeadbeef
+
+#define BALLOON_ENTRY    "balloon"
+extern struct proc_dir_entry *xeno_base;
+
+static struct proc_dir_entry *balloon_pde;
+unsigned long credit;
+
+static inline unsigned long get_ppte(unsigned long addr)
+{
+    unsigned long ppte;
+    pgd_t *pgd; pmd_t *pmd; pte_t *ptep;
+    pgd = pgd_offset_k(addr);
+
+    if ( pgd_none(*pgd) || pgd_bad(*pgd) ) BUG();
+
+    pmd = pmd_offset(pgd, addr);
+    if ( pmd_none(*pmd) || pmd_bad(*pmd) ) BUG();
+
+    ptep = pte_offset(pmd, addr);
+    ppte = (unsigned long)__pa(ptep);
+
+    return ppte;
+}
+
+/* main function for relinquishing bit of memory */
+static unsigned long inflate_balloon(unsigned long num_pages)
+{
+    dom_mem_op_t dom_mem_op;
+    unsigned long *parray;
+    unsigned long *currp;
+    unsigned long ret = 0;
+    unsigned long vaddr;
+    unsigned long i, j;
+
+    parray = (unsigned long *)kmalloc(num_pages *
+                                      sizeof(unsigned long), GFP_KERNEL);
+    currp = parray;
+
+    for ( i = 0; i < num_pages; i++ )
+    {
+        /* try to obtain a free page, has to be done with GFP_ATOMIC
+         * as we do not want to sleep indefinately.
+         */
+        vaddr = __get_free_page(GFP_ATOMIC);
+
+        /* if allocation fails, free all reserved pages */
+        if(!vaddr){
+            printk("Unable to inflate balloon by %ld, only %ld pages free.",
+                   num_pages, i);
+            currp = parray;
+            for(j = 0; j < i; j++){
+                free_page(*currp++);
+            }
+            goto cleanup;
+        }
+
+        *currp++ = vaddr;
+    }
+
+
+    currp = parray;
+    for ( i = 0; i < num_pages; i++ )
+    {
+        queue_l1_entry_update(get_ppte(*currp) | PGREQ_NORMAL, 0);
+        phys_to_machine_mapping[__pa(*currp) >> PAGE_SHIFT] = DEAD;
+        currp++;
+    }
+
+    XENO_flush_page_update_queue();
+
+    dom_mem_op.op = BALLOON_INFLATE_OP;
+    dom_mem_op.u.balloon_inflate.size  = num_pages;
+    dom_mem_op.u.balloon_inflate.pages = parray;
+    if ( (ret = HYPERVISOR_dom_mem_op(&dom_mem_op)) != num_pages )
+    {
+        printk("Unable to deflate balloon, error %lx\n", ret);
+        goto cleanup;
+    }
+
+    credit += num_pages;
+    ret = num_pages;
+
+ cleanup:
+    kfree(parray);
+
+    return ret;
+}
+
+/* install new mem pages obtained by deflate_balloon. function walks 
+ * phys->machine mapping table looking for DEAD entries and populates
+ * them.
+ */
+static unsigned long process_new_pages(unsigned long * parray, 
+                                       unsigned long num)
+{
+    /* currently, this function is rather simplistic as 
+     * it is assumed that domain reclaims only number of 
+     * pages previously released. this is to change soon
+     * and the code to extend page tables etc. will be 
+     * incorporated here.
+     */
+     
+    unsigned long tot_pages = start_info.nr_pages;   
+    unsigned long * curr = parray;
+    unsigned long num_installed;
+    unsigned long i;
+
+    num_installed = 0;
+    for ( i = 0; i < tot_pages; i++ )
+    {
+        if ( phys_to_machine_mapping[i] == DEAD )
+        {
+            phys_to_machine_mapping[i] = *curr;
+            queue_l1_entry_update((i << PAGE_SHIFT) | PGREQ_MPT_UPDATE, i);
+            queue_l1_entry_update(
+                get_ppte((unsigned long)__va(i << PAGE_SHIFT)) | PGREQ_NORMAL, 
+                ((*curr) << PAGE_SHIFT) | L1_PROT);
+
+            *curr = (unsigned long)__va(i << PAGE_SHIFT);
+            curr++;
+            num_installed++;
+        }
+    }
+
+    /* now, this is tricky (and will also change for machine addrs that 
+      * are mapped to not previously released addresses). we free pages
+      * that were allocated by get_free_page (the mappings are different 
+      * now, of course).
+      */
+    curr = parray;
+    for ( i = 0; i < num_installed; i++ )
+    {
+        free_page(*curr);
+        curr++;
+    }
+
+    return num_installed;
+}
+
+static unsigned long deflate_balloon(unsigned long num_pages)
+{
+    dom_mem_op_t dom_mem_op;
+    unsigned long ret;
+    unsigned long * parray;
+
+    if ( num_pages > credit )
+    {
+        printk("Can not allocate more pages than previously released.\n");
+        return -EAGAIN;
+    }
+
+    parray = (unsigned long *)kmalloc(num_pages * sizeof(unsigned long), 
+                                      GFP_KERNEL);
+
+    dom_mem_op.op = BALLOON_DEFLATE_OP;
+    dom_mem_op.u.balloon_deflate.size = num_pages;
+    dom_mem_op.u.balloon_deflate.pages = parray;
+    if((ret = HYPERVISOR_dom_mem_op(&dom_mem_op)) != num_pages){
+        printk("Unable to deflate balloon, error %lx\n", ret);
+        goto cleanup;
+    }
+
+    if((ret = process_new_pages(parray, num_pages)) < num_pages){
+        printk("Unable to deflate balloon by specified %lx pages, only %lx.\n",
+               num_pages, ret);
+        goto cleanup;
+    }
+
+    ret = num_pages;
+
+ cleanup:
+    kfree(parray);
+
+    return ret;
+}
+
+static int balloon_write(struct file *file, const char *buffer,
+                         u_long count, void *data)
+{
+    user_balloon_op_t bop;
+
+    /* Only admin can play with the balloon :) */
+    if ( !capable(CAP_SYS_ADMIN) )
+        return -EPERM;
+
+    if ( copy_from_user(&bop, buffer, sizeof(bop)) )
+        return -EFAULT;
+
+    switch ( bop.op )
+    {
+    case USER_INFLATE_BALLOON:
+        if ( inflate_balloon(bop.size) < bop.size )
+            return -EAGAIN;
+        break;
+        
+    case USER_DEFLATE_BALLOON:
+        deflate_balloon(bop.size);
+        break;
+
+    default:
+        printk("Unknown command to balloon driver.");
+        return -EFAULT;
+    }
+
+    return sizeof(bop);
+}
+
+/*
+ * main balloon driver initialization function.
+ */
+static int __init init_module(void)
+{
+    printk(KERN_ALERT "Starting Xeno Balloon driver\n");
+
+    credit = 0;
+
+    balloon_pde = create_proc_entry(BALLOON_ENTRY, 0600, xeno_base);
+    if ( balloon_pde == NULL )
+    {
+        printk(KERN_ALERT "Unable to create balloon driver proc entry!");
+        return -1;
+    }
+
+    balloon_pde->write_proc = balloon_write;
+
+    return 0;
+}
+
+static void __exit cleanup_module(void)
+{
+}
+
+module_init(init_module);
+module_exit(cleanup_module);
+
+
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/dom_mem_ops.h b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/balloon/dom_mem_ops.h
new file mode 100644 (file)
index 0000000..c473f19
--- /dev/null
@@ -0,0 +1,32 @@
+/******************************************************************************
+ * dom_mem_ops.h
+ *
+ * Header file supporting domain related memory operations. N.B. keep in sync
+ * with xen version. 
+ *
+ * Copyright (c) 2003, B Dragovic
+ */
+
+#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED)
+#define BALLOON_DEFLATE_OP   0
+#define BALLOON_INFLATE_OP   1
+
+typedef struct balloon_deflate_op {
+    unsigned long   size;
+    unsigned long   * pages;
+} balloon_def_op_t;
+
+typedef struct balloon_inflate_op {
+    unsigned long   size;
+    unsigned long   * pages;
+} balloon_inf_op_t;
+
+typedef struct dom_mem_ops
+{
+    unsigned int op;
+    union
+    {
+        balloon_def_op_t balloon_deflate;
+        balloon_inf_op_t balloon_inflate;
+    }u;
+} dom_mem_op_t;
index f8af85358b5b5f84d09a22f3e4010e66131cf721..c36ab02e96da9a410153b559a57e673fe4e10a51 100644 (file)
@@ -53,7 +53,7 @@ typedef struct proc_mem_data {
 
 #define MAP_DISCONT     1
 
-static struct proc_dir_entry *xeno_base;
+struct proc_dir_entry *xeno_base;
 static struct proc_dir_entry *dom0_cmd_intf;
 static struct proc_dir_entry *proc_ft;
 
index df255987300dbad5fd44f9f1981a6ddd47f58882..16f37cfe65340bdb7187e85705ff67db46cf56fd 100644 (file)
@@ -313,4 +313,15 @@ static inline int HYPERVISOR_set_fast_trap(int idx)
     return ret;
 }
 
+static inline int HYPERVISOR_dom_mem_op(void *dom_mem_op)
+{
+    int ret;
+    __asm__ __volatile__ (
+        TRAP_INSTR
+        : "=a" (ret) : "0" (__HYPERVISOR_dom_mem_op),
+        "b" (dom_mem_op) : "memory" );
+
+    return ret;
+}
+
 #endif /* __HYPERVISOR_H__ */
index e157a31a362280a45a6f65d7586e17ec79928c6f..aad36820b7b8473428f75b6b104d3353a9416ca4 100644 (file)
@@ -173,6 +173,10 @@ static __inline__ int get_order(unsigned long size)
 #define VM_DATA_DEFAULT_FLAGS  (VM_READ | VM_WRITE | VM_EXEC | \
                                 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
+/* VIRT <-> MACHINE conversion */
+#define virt_to_machine(_a) (phys_to_machine(__pa(_a)))
+#define machine_to_virt(_m) (__va(machine_to_phys(_m)))
+
 #endif /* __KERNEL__ */
 
 #endif /* _I386_PAGE_H */